package com.candykingdom.base
{
	import com.candykingdom.events.ControlEvent;
	import com.candykingdom.system.Systems;
	
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.TouchEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;
	import flash.utils.getTimer;
	
	[Event(name="control_down", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_up", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_move", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_click", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_over", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_out", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_roll_over", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_roll_out", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_drag_start", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_drag_move", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_drag_stop", type="com.candykingdom.events.ControlEvent")]
	[Event(name="control_drag_cast", type="com.candykingdom.events.ControlEvent")]
	
	public class Display_ghost extends MovieClip
	{
		public function Display_ghost()
		{
			super();
		}
		
		
		
		
		/**------------------------------------------------------------------------------------
		 * 
		 * other
		 * 
		 * 
		 * 
		 * 
		 -------------------------------------------------------------------------------------*/
		
		
		
		
		
		
		
		/**------------------------------------------------------------------------------------
		 * 
		 * 移动处理
		 * 
		 * 
		 * 
		 * 
		 -------------------------------------------------------------------------------------*/
		private const _display:Sprite = new Sprite();
		private const _drawMatrix:Matrix = new Matrix();
		private var _bitmapData:BitmapData;
		private var _drawRect:Rectangle;
		private var _viewRect:Rectangle;
		private var _repeat:Boolean;
		private var _moveX:Number = 0;
		private var _moveY:Number = 0;
		
		/** 画布X坐标 */
		public function get moveX():Number {return _moveX;}
		
		/** 画布Y坐标 */
		public function get moveY():Number {return _moveY;}
		
		
		/**
		 * 清除画布，显示所有原始显示对象，并根据画布tx,ty 更新原始显示对象坐标为画布 x,y 坐标
		 * 
		 */		
		public function clear():void
		{
			if(_bitmapData==null)return;
			
			_bitmapData.dispose();
			_bitmapData = null;
			
			for(var i:int=0;i<numChildren;i++)
			{
				getChildAt(i).visible = true;
				getChildAt(i).x += _moveX;
				getChildAt(i).y += _moveY;
			}
			
			_display.graphics.clear();
			removeChild(_display);
			
			Systems.gc();
		}
		
		
		/**
		 * 画出内部所有显示对象 
		 * @param viewRect
		 * @param repeat
		 * @param transparent
		 * @param fillColor
		 * 
		 */		
		public function draw(viewRect:Rectangle ,repeat:Boolean=true ,transparent:Boolean=true, fillColor:uint=4.294967295E9):void
		{
			_repeat = repeat;
			_viewRect = viewRect;
			
			if(_bitmapData!=null)return;
			_drawRect = getBounds(this);
			
			_bitmapData = new BitmapData
				(Math.max(_drawRect.width ,_viewRect.width) 
				,Math.max(_drawRect.height ,_viewRect.height)
				,transparent 
				,fillColor);
			
			//因为 repeat 设置为 false 时，位图填充将对位图外部的填充区域使用边缘像素：
			//所以这里 减去 1 个像素 来填充背景
			var matrix:Matrix = new Matrix(1 ,0 ,0 ,1 ,-_drawRect.x ,-_drawRect.y);
			_bitmapData.draw(this ,matrix ,null ,null ,new Rectangle(1,1,_bitmapData.width-2,_bitmapData.height-2) ,true);
			
			for(var i:int=0;i<numChildren;i++)
				getChildAt(i).visible = false;
			
			//因为内部要有元件才点区域交互热点，所以没有用自身来 Graphics;
			addChild(_display);
			_display.x = _display.y = 0;
			
			move(_drawRect.x ,_drawRect.y);
			matrix = null;
			Systems.gc();
		}
		
		
		/** 移动画布(渲染) */
		public function move(mX:Number=0 ,mY:Number=0):void
		{
			_moveX = mX;
			_moveY = mY;
			_drawMatrix.tx = _drawRect.x+_moveX;
			_drawMatrix.ty = _drawRect.y+_moveY;
			
			_display.graphics.clear();
			_display.graphics.beginBitmapFill(_bitmapData ,_drawMatrix ,_repeat ,true);
			_display.graphics.drawRect(0 ,0 ,_viewRect.width ,_viewRect.height);
			_display.graphics.endFill();
		}
		
		
		
		
		/**------------------------------------------------------------------------------------
		 * 
		 * 重写事件区 主要用于自动判断操作事件，在PC上则自动使用Mouse 在Mobile上则自动使用Touch
		 * 
		 * 
		 * 
		 * 
		 -------------------------------------------------------------------------------------*/
		override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
		{
			super.addEventListener(type, listener, useCapture, priority, useWeakReference);
			
			if(Multitouch.inputMode == MultitouchInputMode.NONE)
			{
				switch(type)
				{
					case ControlEvent.DOWN:			addEventListener(MouseEvent.MOUSE_DOWN ,mouseHandler);		return;
					case ControlEvent.UP:			addEventListener(MouseEvent.MOUSE_UP ,mouseHandler);		return;
					case ControlEvent.MOVE:			addEventListener(MouseEvent.MOUSE_MOVE ,mouseHandler);		return;
					case ControlEvent.CLICK:		addEventListener(MouseEvent.CLICK ,mouseHandler);			return;
					case ControlEvent.OVER:			addEventListener(MouseEvent.MOUSE_OVER ,mouseHandler);		return;
					case ControlEvent.OUT:			addEventListener(MouseEvent.MOUSE_OUT ,mouseHandler);		return;
					case ControlEvent.ROLL_OVER:	addEventListener(MouseEvent.ROLL_OVER ,mouseHandler);		return;
					case ControlEvent.ROLL_OUT:		addEventListener(MouseEvent.ROLL_OUT ,mouseHandler);		return;
				}
			}else{
				switch(type)
				{
					case ControlEvent.DOWN:			addEventListener(TouchEvent.TOUCH_BEGIN ,touchHandler);		return;
					case ControlEvent.UP:			addEventListener(TouchEvent.TOUCH_END ,touchHandler);		return;
					case ControlEvent.MOVE:			addEventListener(TouchEvent.TOUCH_MOVE ,touchHandler);		return;
					case ControlEvent.CLICK:		addEventListener(TouchEvent.TOUCH_TAP ,touchHandler);		return;
					case ControlEvent.OVER:			addEventListener(TouchEvent.TOUCH_OVER ,touchHandler);		return;
					case ControlEvent.OUT:			addEventListener(TouchEvent.TOUCH_OUT ,touchHandler);		return;
					case ControlEvent.ROLL_OVER:	addEventListener(TouchEvent.TOUCH_ROLL_OVER ,touchHandler);	return;
					case ControlEvent.ROLL_OUT:		addEventListener(TouchEvent.TOUCH_ROLL_OUT ,touchHandler);	return;
				}
			}
		}
		
		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
		{
			super.removeEventListener(type, listener, useCapture);
			
			switch(type)
			{
				case ControlEvent.DOWN:			
					removeEventListener(MouseEvent.MOUSE_DOWN ,mouseHandler);
					removeEventListener(TouchEvent.TOUCH_BEGIN ,touchHandler);
					return;
				case ControlEvent.UP:			
					removeEventListener(MouseEvent.MOUSE_UP ,mouseHandler);			
					removeEventListener(TouchEvent.TOUCH_END ,touchHandler);
					return;
				case ControlEvent.MOVE:			
					removeEventListener(MouseEvent.MOUSE_MOVE ,mouseHandler);
					removeEventListener(TouchEvent.TOUCH_MOVE ,touchHandler);
					return;
				case ControlEvent.CLICK:		
					removeEventListener(MouseEvent.CLICK ,mouseHandler);
					removeEventListener(TouchEvent.TOUCH_TAP ,touchHandler);
					return;
				case ControlEvent.OVER:			
					removeEventListener(MouseEvent.MOUSE_OVER ,mouseHandler);		
					removeEventListener(TouchEvent.TOUCH_OVER ,touchHandler);
					return;
				case ControlEvent.OUT:			
					removeEventListener(MouseEvent.MOUSE_OUT ,mouseHandler);
					removeEventListener(TouchEvent.TOUCH_OUT ,touchHandler);
					return;
				case ControlEvent.ROLL_OVER:	
					removeEventListener(MouseEvent.ROLL_OVER ,mouseHandler);			
					removeEventListener(TouchEvent.TOUCH_ROLL_OVER ,touchHandler);
					return;
				case ControlEvent.ROLL_OUT:		
					removeEventListener(MouseEvent.ROLL_OUT ,mouseHandler);			
					removeEventListener(TouchEvent.TOUCH_ROLL_OUT ,touchHandler);
					return;
			}
		}
		
		private function mouseHandler(event:MouseEvent):void
		{
			var data:Object = new Object();
			data.localX = event.localX;
			data.localY = event.localY;
			data.stageX = event.stageX;
			data.stageY = event.stageY;
			
			data.touchPointID = 0;
			data.pressure = 0;
			data.sizeX = 0;
			data.sizeY = 0;
			data.timestamp = getTimer();
			
			dispatchHandler(event.type ,data);
		}
		
		private function touchHandler(event:TouchEvent):void
		{
			var data:Object = new Object();
			data.localX = event.localX;
			data.localY = event.localY;
			data.stageX = event.stageX;
			data.stageY = event.stageY;
			
			data.touchPointID = event.touchPointID;
			data.pressure = event.pressure;
			data.sizeX = event.sizeX;
			data.sizeY = event.sizeY;
			data.timestamp = getTimer();//event.timestamp;
			
			dispatchHandler(event.type ,data);
		}
		
		private function dispatchHandler(type:String ,data:Object):void
		{
			switch(type)
			{
				case MouseEvent.MOUSE_DOWN:			dispatchEvent(new ControlEvent(ControlEvent.DOWN ,data));		return;
				case MouseEvent.MOUSE_UP:			dispatchEvent(new ControlEvent(ControlEvent.UP ,data));			return;
				case MouseEvent.MOUSE_MOVE:			dispatchEvent(new ControlEvent(ControlEvent.MOVE ,data));		return;
				case MouseEvent.CLICK:				dispatchEvent(new ControlEvent(ControlEvent.CLICK ,data));		return;
				case MouseEvent.MOUSE_OVER:			dispatchEvent(new ControlEvent(ControlEvent.OVER ,data));		return;
				case MouseEvent.MOUSE_OUT:			dispatchEvent(new ControlEvent(ControlEvent.OUT ,data));		return;
				case MouseEvent.ROLL_OVER:			dispatchEvent(new ControlEvent(ControlEvent.ROLL_OVER ,data));	return;
				case MouseEvent.ROLL_OUT:			dispatchEvent(new ControlEvent(ControlEvent.ROLL_OUT ,data));	return;
				
				case TouchEvent.TOUCH_BEGIN:		dispatchEvent(new ControlEvent(ControlEvent.DOWN ,data));		return;
				case TouchEvent.TOUCH_END:			dispatchEvent(new ControlEvent(ControlEvent.UP ,data));			return;
				case TouchEvent.TOUCH_MOVE:			dispatchEvent(new ControlEvent(ControlEvent.MOVE ,data));		return;
				case TouchEvent.TOUCH_TAP:			dispatchEvent(new ControlEvent(ControlEvent.CLICK ,data));		return;
				case TouchEvent.TOUCH_OVER:			dispatchEvent(new ControlEvent(ControlEvent.OVER ,data));		return;
				case TouchEvent.TOUCH_OUT:			dispatchEvent(new ControlEvent(ControlEvent.OUT ,data));		return;
				case TouchEvent.TOUCH_ROLL_OVER:	dispatchEvent(new ControlEvent(ControlEvent.ROLL_OVER ,data));	return;
				case TouchEvent.TOUCH_ROLL_OUT:		dispatchEvent(new ControlEvent(ControlEvent.ROLL_OUT ,data));	return;
			}
		}
		
		
		
		
		
		
		
		/**------------------------------------------------------------------------------------
		 * 
		 * 拖动事件处理
		 * 
		 * 
		 * 
		 * 
		 -------------------------------------------------------------------------------------*/
		
		private var _startPoint:Point = new Point();
		private var _endPoint:Point = new Point();
		private var _drag:Boolean;
		private var _cast:Boolean;
		private var _controlTimer:int;
		private var _enabledDrag:Boolean;
		
		
		/** 是否开启拖动 */
		public function get enabledDrag():Boolean {return _enabledDrag;}
		
		public function set enabledDrag(value:Boolean):void
		{
			_enabledDrag = value;
			if(_enabledDrag)
			{
				if(Multitouch.inputMode == MultitouchInputMode.NONE)
				{
					addEventListener(MouseEvent.MOUSE_DOWN ,dragMouseHandler);
				}else{
					addEventListener(TouchEvent.TOUCH_BEGIN ,dragTouchHandler);
				}
			}else{
				removeEventListener(MouseEvent.MOUSE_DOWN ,dragMouseHandler);
				removeEventListener(TouchEvent.TOUCH_BEGIN ,dragTouchHandler);
				stage.removeEventListener(MouseEvent.MOUSE_MOVE ,dragMouseHandler);
				stage.removeEventListener(TouchEvent.TOUCH_MOVE ,dragTouchHandler);
				stage.removeEventListener(MouseEvent.MOUSE_UP ,dragMouseHandler);
				stage.removeEventListener(TouchEvent.TOUCH_END ,dragTouchHandler);
			}
		}
		
		
		/** MouseEvent */
		private function dragMouseHandler(event:MouseEvent):void
		{
			dragHandler(event.type);
		}
		
		/** ToucehEvent */
		private function dragTouchHandler(event:TouchEvent):void
		{
			if(event.touchPointID!=0)return;
			dragHandler(event.type);
		}
		
		/** 主逻辑处理 */
		private function dragHandler(type:String):void
		{
			switch(type)
			{
				case MouseEvent.MOUSE_DOWN:case TouchEvent.TOUCH_BEGIN:
					_drag = false;
					_cast = false;
					_startPoint.x = mouseX;
					_startPoint.y = mouseY;
					_controlTimer = getTimer();
					stage.addEventListener(MouseEvent.MOUSE_MOVE ,dragMouseHandler);
					stage.addEventListener(TouchEvent.TOUCH_MOVE ,dragTouchHandler);
					stage.addEventListener(MouseEvent.MOUSE_UP ,dragMouseHandler);
					stage.addEventListener(TouchEvent.TOUCH_END ,dragTouchHandler);
					return;
					
				case MouseEvent.MOUSE_MOVE:case TouchEvent.TOUCH_MOVE:
					_endPoint.x = mouseX;
					_endPoint.y = mouseY;
					
					if(!_drag && !_cast)
					{
						if(getTimer() - _controlTimer<35)
						{
							stage.removeEventListener(MouseEvent.MOUSE_MOVE ,dragMouseHandler);
							stage.removeEventListener(TouchEvent.TOUCH_MOVE ,dragTouchHandler);
							_cast = true;
						}
						
						if(getTimer() - _controlTimer>65)
						{
							_drag = true;
							dragDispatchHandler(ControlEvent.DRAG_START);
						}
						
						_controlTimer = getTimer();
					}
					
					if(_drag)
					{
						dragDispatchHandler(ControlEvent.DRAG_MOVE);
					}
					return;
					
				case MouseEvent.MOUSE_UP:case TouchEvent.TOUCH_END:
					stage.removeEventListener(MouseEvent.MOUSE_MOVE ,dragMouseHandler);
					stage.removeEventListener(TouchEvent.TOUCH_MOVE ,dragTouchHandler);
					stage.removeEventListener(MouseEvent.MOUSE_UP ,dragMouseHandler);
					stage.removeEventListener(TouchEvent.TOUCH_END ,dragTouchHandler);
					_endPoint.x = mouseX;
					_endPoint.y = mouseY;
					
					if(_drag)
						dragDispatchHandler(ControlEvent.DRAG_STOP);
					
					if(_cast && getTimer() - _controlTimer<100 && Point.distance(_startPoint ,_endPoint)>50)
						dragDispatchHandler(ControlEvent.DRAG_CAST);
					
					_drag = false;
					_cast = false;
					return;
			}
		}
		
		/** 发送事件，并设置对应参数 */
		private function dragDispatchHandler(type:String):void
		{
			var data:Object = new Object();
			data.startPoint = _startPoint;
			data.endPoint = _endPoint;
			data.direction = getDirection(_startPoint ,_endPoint);
			dispatchEvent(new ControlEvent(type ,data));
		}
		
		/** 计算方向 */
		private function getDirection(start:Point ,end:Point):int
		{
			if(Math.abs(end.y-start.y)>Math.abs(end.x-start.x))
			{
				return end.y<start.y?0:1;
			}else{
				return end.x<start.x?2:3;
			}
		}
	}
}